#include "string.h"

using namespace windows::kernal;

NTSTATUS String::ConvertWcharToChar(PCWSTR source, PSTR destination,
                                    SIZE_T &size) {
  PAGED_CODE();

  NTSTATUS status;
  ULONG required_size;
  ANSI_STRING ansi;
  UNICODE_STRING unicode;

  if (!source) return STATUS_INVALID_PARAMETER_1;
  if (!destination) return STATUS_INVALID_PARAMETER_2;
  if (!size) return STATUS_INVALID_PARAMETER_3;

  RtlInitUnicodeString(&unicode, source);
  required_size = RtlUnicodeStringToAnsiSize(&unicode);
  if (size < required_size) {
    size = required_size;
    return STATUS_BUFFER_TOO_SMALL;
  }
  ansi.Length = 0;
  ansi.MaximumLength = (USHORT)size;
  ansi.Buffer = destination;
  status = RtlUnicodeStringToAnsiString(&ansi, &unicode, FALSE);
  if (NT_SUCCESS(status)) {
    if (ansi.Length < ansi.MaximumLength) {
      ansi.Buffer[ansi.Length] = ANSI_NULL;
    } else {
      ansi.Buffer[ansi.MaximumLength - 1] = ANSI_NULL;
    }
  }

  return status;
}

NTSTATUS String::ConvertCharToWchar(PCSTR source, PWSTR destination,
                                    SIZE_T &size) {
  PAGED_CODE();

  NTSTATUS status;
  ULONG required_size;
  ANSI_STRING ansi;
  UNICODE_STRING unicode;

  if (!source) return STATUS_INVALID_PARAMETER_1;
  if (!destination) return STATUS_INVALID_PARAMETER_2;
  if (!size) return STATUS_INVALID_PARAMETER_3;

  RtlInitAnsiString(&ansi, source);
  required_size = RtlAnsiStringToUnicodeSize(&ansi);
  if (size <= required_size) {
    size = required_size;
    return STATUS_BUFFER_TOO_SMALL;
  }
  unicode.Length = 0;
  unicode.MaximumLength = (USHORT)size;
  unicode.Buffer = destination;
  status = RtlAnsiStringToUnicodeString(&unicode, &ansi, FALSE);
  if (NT_SUCCESS(status)) {
    if (unicode.Length < unicode.MaximumLength) {
      unicode.Buffer[unicode.Length] = UNICODE_NULL;
    } else {
      unicode.Buffer[unicode.MaximumLength - 1] = UNICODE_NULL;
    }
  }

  return status;
}
